package com.voltmao.webpro.utils.http;

import com.google.gson.internal.LinkedTreeMap;
import com.voltmao.webpro.utils.JsonUtil;
import com.voltmao.webpro.utils.StringUtils;
import com.voltmao.webpro.utils.io.InputStreamUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Map;

/**
 * Created by zhouyang on 2017/2/23.
 */
public class HttpsClientUtils {
    private static Log log = LogFactory.getLog(HttpRequestUtil.class);


    /**
     * 回调方法事件
     */
    public interface HttpsClientCall {
        /**
         * 调用成功回调用函数
         *
         * @param data
         * @throws IOException
         * @throws NoSuchAlgorithmException
         */
        void success(String data) throws IOException, NoSuchAlgorithmException;
    }

    /**
     * 默认的(TLS)GET请求
     *
     * @param url
     * @param params
     * @param httpsClientCall
     * @throws IOException
     */
    public static synchronized String sendSSLGet(String url, Map<String, Object> params, HttpsClientCall httpsClientCall) {
        // 拼接参数
        String newurl = HttpClientUtil.uriBuilder(url, params);
        HttpGet httpGet = new HttpGet(newurl);

        String resultStr = null;
        try {
            resultStr = sendSSLRequest(httpGet, null);
            if (httpsClientCall != null) {
                httpsClientCall.success(resultStr);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }

        log.info("return info: " + resultStr);

        return resultStr;
    }

    /**
     * 默认的(TLS)Post请求
     *
     * @param url
     * @param params
     * @param httpsClientCall
     * @throws IOException
     */
    public static synchronized String sendSSLPost(String url, Map<String, Object> params, HttpsClientCall httpsClientCall) throws IOException, NoSuchAlgorithmException, KeyManagementException {
        // 拼接参数
        String newurl = HttpClientUtil.uriBuilder(url, params);
        HttpPost httpPost = new HttpPost(newurl);

        String resultStr = sendSSLRequest(httpPost, null);
        log.info("return info: " + resultStr);

        httpsClientCall.success(resultStr);

        return resultStr;
    }

    /**
     * 默认的(TLS)Post请求
     *
     * @param url
     * @param httpsClientCall
     * @throws IOException
     */
    public static synchronized String sendSSLPost(String url, PostReportData requestData, HttpsClientCall httpsClientCall) {
        //拼接参数
        String newurl = HttpClientUtil.uriBuilder(url, requestData.getRequestParams());
        HttpPost httpPost = new HttpPost(newurl);

        try {
            //设置二机制流数据
            InputStream instream = InputStreamUtils.StringTOInputStream(requestData.getOutStr(), "GBK");

            if (instream != null) {
                InputStreamEntity inputEntry = new InputStreamEntity(instream);
                httpPost.setEntity(inputEntry);
            }

            //设置所有的请求头
            requestData.builderHttpPostHeader(httpPost);

            requestData.builderHttpCookie(httpPost);

            String resultStr = sendSSLRequest(httpPost, null);
            log.info("return info: " + resultStr);

            System.out.println(resultStr);
            httpsClientCall.success(resultStr);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }

        return newurl;
    }

    /**
     * 默认的(TLS)Post请求
     *
     * @param url
     * @param httpsClientCall
     * @throws IOException
     */
    public static synchronized String sendSSLPost(String url, SSLContext sslContext, PostReportData requestData, HttpsClientCall httpsClientCall) {
        String resultStr = "";

        // 拼接参数
        String newurl = HttpClientUtil.uriBuilder(url, requestData.getRequestParams());
        HttpPost httpPost = new HttpPost(newurl);

        try {
            //设置二机制流数据
            InputStream instream = InputStreamUtils.StringTOInputStream(requestData.getOutStr(), "utf-8");

            if (instream != null) {
                InputStreamEntity inputEntry = new InputStreamEntity(instream);
                httpPost.setEntity(inputEntry);
            }

            //设置所有的请求头
            requestData.builderHttpPostHeader(httpPost);

            resultStr = sendSSLRequest(httpPost, sslContext);

            log.info("return info: " + resultStr);

            if (httpsClientCall != null) {
                httpsClientCall.success(resultStr);
            }
        } catch (Exception e) {
            resultStr = e.toString();
            e.printStackTrace();
        }

        return resultStr;
    }


    /**
     * 得到默认非验证SSL上下文
     *
     * @return
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     */
    private static SSLContext getDefaultSSLContent() throws NoSuchAlgorithmException, KeyManagementException {
        // 创建TrustManager
        X509TrustManager xtm = new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };

        // 创建SSLContext
        SSLContext ctx = SSLContext.getInstance("TLSv1");
        ctx.init(null, new TrustManager[]{xtm}, null);

        return ctx;
    }

    /**
     * 发起TLS证书的请求
     *
     * @param request
     * @return
     */
    private static String sendSSLRequest(HttpUriRequest request, SSLContext sslContext) throws IOException, NoSuchAlgorithmException, KeyManagementException {
        String result = "";

        //获取默认sslcontent||传入的sslcontent
        SSLContext ctx = sslContext == null ? getDefaultSSLContent() : sslContext;
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                ctx,
                new String[]{"TLSv1"},
                null,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

        //建立连接
        CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        try {

            HttpResponse response = httpClient.execute(request);
            HttpEntity entity = response.getEntity();

//            System.out.println("sdfdsf"+JsonUtil.ObjectToJSON(context.getCookieStore()));

            result = EntityUtils.toString(entity, "UTF-8");

        } catch (ClientProtocolException e) {
            log.error("客户端协议异常，连接失败！", e);
            throw new RuntimeException("客户端协议异常，连接失败！", e);
        } finally {
            httpClient.close();
            log.info("关闭连接");
        }

        return result;
    }


    public static void main(String[] args) throws IOException, NoSuchAlgorithmException {

        updateWorkTime("start");
//        updateWorkTime("end");

//        loginSys();
    }

    /**
     * 隐藏方法
     *
     * @param type
     * @throws IOException
     * @throws NoSuchAlgorithmException
     */
    private static void updateWorkTime(String type) throws IOException, NoSuchAlgorithmException {

        final String host = "https://app.woqu365.com/";
        final String sendUrl = "app/employee/sign4gps.htm";

        //提交的数据包
        final PostReportData requestData = new PostReportData();
        requestData.addHeaderInfo("Client-Type", "iphone");
        requestData.addHeaderInfo("Invoke-Type", "ajax");
        requestData.addHeaderInfo("Client-Name", "%E5%91%A8%E6%9D%A8%E7%9A%84%20iPhone");
        requestData.addHeaderInfo("Client-Model", "iPhone 5S");
        requestData.addHeaderInfo("Client-Version", "1.3.5-2016012311");
        requestData.addHeaderInfo("Client-OS", "10.0.2");
        requestData.addHeaderInfo("Accept-Language", "zh-cn");
        requestData.addHeaderInfo("Client-Version", "1.3.5-2016012311");
        requestData.addHeaderInfo("Content-Type", "application/octet-stream");
        requestData.addHeaderInfo("Client-UUID", "6E101EBA-AADB-48D1-85FC-4C73F68313EE");
        requestData.addHeaderInfo("User-Agent", "Attendance/2016012311 CFNetwork/808.0.2 Darwin/16.0.0");
        requestData.addHeaderInfo("Cookie", "_ai_=\"h1X218nUmu9Tzr0GUSd2kjhC1wdzDCxV8bVgHMqF3H0nrcXR+8JHNovgfZmQGmB6EZNYJ4TO7JuRY0YiOgyx164cXeh9bDW6NmX5BYqfTt5rYZjJMLIWHnorHSYZalaulCW29knsdzo=\"; _wcfl_=\"aWumapF+jJ8LTRtg9D0RK280QhWfznJ0\"; _ccode_=IWCIUA; _wcf_=\"4YXwxvESZzG8AqyLwaGMSncSiNd8QD6S16cxOMsRAcFRSFLy3G4n6M26060ogZvt9oVKSENswAJ95q3eUUvdUQ4BnZb1PGMhOl8FlkSWZmHb0sn7+2p1V0Wq1kygxO3AR7OfVxjcIPAj6/j0/xCkmg==\"");

        requestData.addCookie("_ai_", "AyJp9aH8/EK0tKrIcIv573hNL3HBBK6brhxd6H1sNbo2ZfkFip9O3mthmMkwshYeeisdJhlqVq4MuMil/+Wp3Nyqy7VbrJplFOEiSaXuc22L4H2ZkBpgehGTWCeEzuyb+iNXh408rmE=");
        requestData.addCookie("_wcfl_", "piAGOMWFy+TOiSixRurmcG80QhWfznJ0");
        requestData.addCookie("_ccode_", "AIWCIUA");
        requestData.addCookie("_ct_", "Pn5uyiFPPexSef0eP7ZGCg==");
        requestData.addCookie("_wcf_", "KPDxe/gMe8hstg0WMPwNKAG694KZnudnSMaWvGW3/pgtKo1tTiCtJQv1CcDC+zX6VxIqtxqjyfvHt8ovNUynfr7od7iovtjiF89A3kVnLDDQsvQ8QUKmOtIzsus4S2AxR7OfVxjcIPAj6/j0/xCkmg==");

        requestData.addRequestParams("group", "1");
        requestData.addRequestParams("longitude", "106.54488681" + StringUtils.randomIntLength(5));
        requestData.addRequestParams("latitude", "29.551372689" + StringUtils.randomIntLength(5));
        requestData.addRequestParams("type", type);
        requestData.addRequestParams("v", "2");

        //step 1:获取操作ID
        HttpsClientUtils.sendSSLPost(host + sendUrl, requestData, new HttpsClientCall() {
            @Override
            public void success(String data) throws IOException, NoSuchAlgorithmException {

                System.out.println("返回:" + data);
                //step 2: 通过操作ID,再提交覆盖时间数据
                LinkedTreeMap<String, Object> map = JsonUtil.ToMap(data);

                List<LinkedTreeMap<String, Object>> actions = ((List<LinkedTreeMap<String, Object>>) ((LinkedTreeMap<String, Object>) map.get("data")).get("actions"));

                //数据包
                PostReportData sendRequestData = new PostReportData();
                sendRequestData.setHeaderData(requestData.getHeaderData());
                sendRequestData.setRequestParams(StringUtils.getUrlParams(actions.get(0).get("url") + ""));

                HttpsClientUtils.sendSSLPost(host + sendUrl, sendRequestData, new HttpsClientCall() {
                    @Override
                    public void success(String data) {
                        System.out.println(data);
                    }
                });
            }
        });
    }

    private static void loginSys() {
        final PostReportData requestData = new PostReportData();
        requestData.addRequestParams("password", "5417492");
        requestData.addRequestParams("phone", "18623080234");


        HttpsClientUtils.sendSSLPost("https://app.woqu365.com/app/login/doLogin.htm", requestData, new HttpsClientCall() {
            @Override
            public void success(String data) throws IOException, NoSuchAlgorithmException {

            }
        });
    }

}

